﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace SIGEB.Prototipo.Vista.configuracionAvanzada.moduloTipoPerfil
{
    public class nodoArbol
    {

        #region "constructores"

        public nodoArbol(CheckBox casilla, nodoArbol padre)
        {
            this.casilla = casilla;
            this.casilla.CheckedChanged += new System.EventHandler(this.CheckedChanged);
            nodos = new LinkedList<nodoArbol>();
            this.padre = padre;
        }

        public nodoArbol(CheckBox casilla, nodoArbol padre, System.EventHandler metodoCheck)
        {
            this.casilla = casilla;
            this.casilla.CheckedChanged += metodoCheck;
            nodos = new LinkedList<nodoArbol>();
            this.padre = padre;
        }

        public nodoArbol(CheckBox casilla, nodoArbol padre, LinkedList<nodoArbol> hijos)
        {
            this.casilla = casilla;
            this.casilla.CheckedChanged += new System.EventHandler(this.CheckedChanged);
            nodos = hijos;
            this.padre = padre;
        }

        #endregion

        #region "métodos"

        public void hijoChangingTrue()
        {
            if (padre != null)
            {
                padre.hijoChanging = true;
                padre.hijoChangingTrue();
            }
        }

        public void hijoChangingFalse()
        {
            if (padre != null)
            {
                padre.hijoChanging = false;
                padre.hijoChangingFalse();
            }
        }

        private void CheckedChanged(object sender, EventArgs e)
        {
            if (!checkUsando)
            {
                checkUsando = true;
                if (esHoja())
                {
                    hijoChangingTrue();
                    padre.notificaCambio();
                    hijoChangingFalse();
                    
                }
                else if(!hijoChanging)
                {
                    if (casilla.Checked)
                    {
                        foreach (nodoArbol act in nodos)
                        {
                            act.seleccionarAuto();
                        }
                    }
                    else
                    {
                        foreach (nodoArbol act in nodos)
                        {
                            act.desSeleccionarAuto();
                        }
                    }
                }
                checkUsando = false;
            }
        }

        public void marcaPermisos(permisosClass p)
        {
            if (esHoja())
            {
                try
                {
                    casilla.Checked = p.getNext() == '1';
                }
                catch
                {
                    casilla.Checked = false;
                }
                padre.notificaCambio();
            }
            else
            {
                foreach (nodoArbol actual in nodos)
                {
                    actual.marcaPermisos(p);
                }
            }
        }

        public string getPermisos(string permisos)
        {
            if (esHoja())
            {
                if (casilla.Checked)
                {
                    permisos += "1";
                }
                else
                {
                    permisos += "0";
                }
                return permisos;
            }
            else
            {
                foreach (nodoArbol actual in nodos)
                {
                    permisos += getPermisos(permisos);
                }
            }
            return permisos;
        }

        public nodoArbol getHijo(int index)
        {
            return nodos.ElementAt(index);
        }

        private void agregarHijo(CheckBox nuevo)
        {
            nodos.AddLast(new nodoArbol(nuevo, this));         
        }

        public void agregarHijos(CheckBox[] nuevos)
        {
            foreach (CheckBox act in nuevos)
            {
                this.nodos.AddLast(new nodoArbol(act, this));
            }
        }

        public void seleccionar()
        {
            casilla.Checked = true;
            foreach (nodoArbol act in nodos)
            {
                act.seleccionar();
            }
            if (padre != null)
            {
                padre.notificaCambio();
            }
        }

        public void seleccionarAuto()
        {
            casilla.Checked = true;
            foreach (nodoArbol act in nodos)
            {
                act.seleccionarAuto();
            }
        }

        public void desSeleccionar()
        {
            casilla.Checked = false;
            foreach (nodoArbol act in nodos)
            {
                act.desSeleccionar();
            }
            if (padre != null)
            {
                padre.notificaCambio();
            }

        }

        public void desSeleccionarAuto()
        {
            casilla.Checked = false;
            foreach (nodoArbol act in nodos)
            {
                act.desSeleccionarAuto();
            }
        }

        private void seleccionarHijo(int index)
        {
            if (index >= nodos.Count)
            {
                throw new IndexOutOfRangeException("Índice del árbol no encontrado");                    
            }
            nodos.ElementAt(index).seleccionar();
        }

        public void desSeleccionarHijo(int index)
        {
            if (index >= nodos.Count)
            {
                throw new IndexOutOfRangeException("Índice del árbol no encontrado");
            }
            nodos.ElementAt(index).desSeleccionar();
        }

        public void notificaCambio()
        {
            if (!esHoja())
            {
                casilla.Checked = todosSeleccionados();
                if (padre != null)
                {
                    padre.notificaCambio();
                }
            }
        }

        public void leerPermiso(permisosClass permisos)
        {
            if (esHoja())
            {
                if (casilla.Checked)
                {
                    permisos.permisos += "1";
                }
                else
                {
                    permisos.permisos += "0";
                }
            }
            else
            {
                foreach (nodoArbol act in nodos)
                {
                    act.leerPermiso(permisos);
                }
            }
            
        }

        private bool todosSeleccionados()
        {
            foreach (nodoArbol act in nodos)
            {
                if (!act.casilla.Checked)
                {
                    return false;
                }
            }
            return true;
        }

        public bool esHoja()
        {
            return nodos.Count == 0;
        }

        public int numHijos()
        {
            return nodos.Count;
        }

        public void Activar()
        {
            casilla.Enabled = true;
            if (!esHoja())
            {
                foreach (nodoArbol act in nodos)
                {
                    act.Activar();
                }
            }
        }

        public void desActivar()
        {
            casilla.Enabled = false;
            if (!esHoja())
            {
                foreach (nodoArbol act in nodos)
                {
                    act.desActivar();
                }
            }
        }

        #endregion

        #region "atributos"

        bool checkUsando = false;
        bool hijoChanging = false;
        CheckBox casilla;
        nodoArbol padre;
        LinkedList<nodoArbol> nodos;

        #endregion
    }
}
